package com.big.codegen.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import com.big.codegen.domain.dto.CodegenTableConfigDTO;
import com.big.codegen.domain.dto.ColumnDTO;
import com.big.codegen.domain.dto.DatasourceDTO;
import com.big.codegen.domain.entity.CodegenTableConfig;
import com.big.codegen.service.CodegenTableConfigService;
import com.big.codegen.service.DatasourceService;
import com.big.codegen.service.TableCodegenService;
import com.big.codegen.util.DatabaseUtils;
import com.big.codegen.util.SqlGeneratorUtils;
import com.big.common.core.exception.CustomerException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *
 * </p>
 *
 * @author 山归岿
 * @create 2025-06-26-19:55
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TableCodegenServiceImpl implements TableCodegenService {
    private final DatasourceService datasourceService;
    private final CodegenTableConfigService codegenTableConfigService;

    @Override
    public String generateSql(String datasourceId, String tableName, String tableComment, List<ColumnDTO> columns) {
        try {
            // 参数校验
            if (datasourceId == null) {
                throw new CustomerException("数据源ID不能为空");
            }
            if (!StringUtils.hasText(tableName)) {
                throw new CustomerException("表名不能为空");
            }
            if (columns == null || columns.isEmpty()) {
                throw new CustomerException("字段列表不能为空");
            }

            // 获取数据源信息
            DatasourceDTO datasource = datasourceService.getByIdDTO(datasourceId);
            if (datasource == null) {
                throw new CustomerException("数据源不存在");
            }

            // 验证数据源连接
            boolean isConnected = DatabaseUtils.testConnection(datasource);
            if (!isConnected) {
                throw new CustomerException("数据源连接失败，请检查数据源配置");
            }

            // 生成创建表的SQL语句
            String createTableSql = SqlGeneratorUtils.generateCreateTableSql(datasource, tableName, tableComment, columns);

            log.info("成功生成表 {} 的SQL语句", tableName);
            return createTableSql;

        } catch (CustomerException e) {
            log.error("生成SQL失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("生成SQL失败", e);
            throw new CustomerException("生成SQL失败: " + e.getMessage());
        }
    }

    @Override
    public boolean createTable(CodegenTableConfigDTO request) {
        Connection connection = null;
        try {
            String sql = generateSql(
                    request.getDatasourceId(),
                    request.getTableName(),
                    request.getTableComment(),
                    request.getColumns()
            );

            // 参数校验
            if (request.getDatasourceId() == null) {
                throw new CustomerException("数据源ID不能为空");
            }
            if (!StringUtils.hasText(sql)) {
                throw new CustomerException("SQL语句不能为空");
            }

            // 获取数据源信息
            DatasourceDTO datasource = datasourceService.getByIdDTO(request.getDatasourceId());
            if (datasource == null) {
                throw new CustomerException("数据源不存在");
            }

            // 获取数据库连接
            connection = DatabaseUtils.getConnection(datasource);
            if (connection == null) {
                throw new CustomerException("获取数据库连接失败");
            }

            // 执行创建表SQL
            try (var statement = connection.createStatement()) {
                statement.execute(sql);
                log.info("成功执行创建表SQL: {}", sql);
                return true;
            }

        } catch (CustomerException e) {
            log.error("创建表失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("创建表失败", e);
            throw new CustomerException("创建表失败: " + e.getMessage());
        } finally {
            DatabaseUtils.closeConnection(connection);
        }
    }

    @Override
    public List<ColumnDTO> getTableColumns(String datasourceId, String tableName) {
        try {
            // 参数校验
            if (datasourceId == null) {
                throw new CustomerException("数据源ID不能为空");
            }
            if (!StringUtils.hasText(tableName)) {
                throw new CustomerException("表名不能为空");
            }

            // 获取数据源信息
            DatasourceDTO datasource = datasourceService.getByIdDTO(datasourceId);
            if (datasource == null) {
                throw new CustomerException("数据源不存在");
            }

            // 获取表字段信息
            List<ColumnDTO> columns = DatabaseUtils.getTableColumns(datasource, tableName);
            log.info("成功获取表 {} 的字段信息，共 {} 个字段", tableName, columns.size());
            return columns;

        } catch (CustomerException e) {
            log.error("获取表字段信息失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("获取表字段信息失败", e);
            throw new CustomerException("获取表字段信息失败: " + e.getMessage());
        }
    }

    @Override
    public List<String> getTableNames(String datasourceId) {
        try {
            // 参数校验
            if (datasourceId == null) {
                throw new CustomerException("数据源ID不能为空");
            }

            // 获取数据源信息
            DatasourceDTO datasource = datasourceService.getByIdDTO(datasourceId);
            if (datasource == null) {
                throw new CustomerException("数据源不存在");
            }

            // 获取所有表名
            List<String> tableNames = DatabaseUtils.getTableNames(datasource);
            log.info("成功获取数据源 {} 的表名列表，共 {} 个表", datasource.getName(), tableNames.size());
            return tableNames;

        } catch (CustomerException e) {
            log.error("获取表名列表失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("获取表名列表失败", e);
            throw new CustomerException("获取表名列表失败: " + e.getMessage());
        }
    }

    @Override
    public Boolean importTables(String datasourceId, List<String> tables) {
        try {
            // 参数校验
            if (datasourceId == null) {
                throw new CustomerException("数据源ID不能为空");
            }
            if (tables == null || tables.isEmpty()) {
                throw new CustomerException("表名列表不能为空");
            }

            // 获取数据源信息
            DatasourceDTO datasource = datasourceService.getByIdDTO(datasourceId);
            if (datasource == null) {
                throw new CustomerException("数据源不存在");
            }

            // 验证数据源连接
            boolean isConnected = DatabaseUtils.testConnection(datasource);
            if (!isConnected) {
                throw new CustomerException("数据源连接失败，请检查数据源配置");
            }

            // 获取数据库中所有表名
            List<String> allTableNames = DatabaseUtils.getTableNames(datasource);
            
            // 验证要导入的表是否存在
            tables.forEach(tableName ->{
                if (!allTableNames.contains(tableName)) {
                    throw new CustomerException("表 '" + tableName + "' 在数据库中不存在");
                }
            });

            // 批量保存表配置信息
            List<CodegenTableConfig> configList = new ArrayList<>();
            for (String tableName : allTableNames) {
                // 获取表字段信息
                List<ColumnDTO> columns = DatabaseUtils.getTableColumns(datasource, tableName);
                
                // 创建表配置对象
                CodegenTableConfig config = new CodegenTableConfig();
                config.setDatasourceId(datasourceId);
                config.setTableName(tableName);
                
                // 从字段信息中获取表注释（通常第一个字段会包含表注释信息）
                String tableComment = "";
                if (!columns.isEmpty()) {
                    // 这里可以根据实际情况调整获取表注释的逻辑
                    // 默认使用表名作为注释
                    tableComment = tableName;
                }
                config.setTableComment(tableComment);
                
                // 生成实体类名（将表名转换为驼峰命名）
                String entityName = CharSequenceUtil.toCamelCase(tableName);
                // 首字母大写
                config.setEntityName(CharSequenceUtil.upperFirst(entityName));
                
                // 设置默认包名
                config.setPackageName("com.big.codegen.domain.entity");
                
                // 设置默认生成路径
                config.setGeneratePath("/src/main/java");
                
                // 设置默认作者
                config.setAuthor("代码生成器");
                
                // 将字段配置转换为JSON字符串
                try {
                    String jsonStr = JSONUtil.toJsonStr(columns);
                    config.setColumnsConfig(jsonStr);
                } catch (Exception e) {
                    log.warn("字段配置序列化失败，表: {}", tableName, e);
                    config.setColumnsConfig("[]");
                }
                
                // 设置状态为草稿
                config.setStatus(1);
                
                // 设置备注
                config.setRemark("通过导入功能创建");
                
                configList.add(config);
            }
            
            // 批量保存到数据库
            codegenTableConfigService.saveBatch(configList);
            log.info("成功导入 {} 张表的配置: {}", allTableNames.size(), allTableNames);
            return true;
            
        } catch (CustomerException e) {
            log.error("导入表配置失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("导入表配置失败", e);
            throw new CustomerException("导入表配置失败: " + e.getMessage());
        }
    }
    
}
